package cn.xingzhe.monster.user.domain.model;

import lombok.Builder;
import lombok.Getter;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 角色领域模型
 * 包含角色相关的业务逻辑和业务规则
 *
 * @author System
 * @version 1.0.0
 * @since 2024-01-01
 */
@Getter
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class RoleModel {

    /**
     * 角色ID
     */
    private String id;

    /**
     * 角色代码（唯一）
     */
    private String roleCode;

    /**
     * 角色名称
     */
    private String roleName;

    /**
     * 角色描述
     */
    private String description;

    /**
     * 权限ID列表
     */
    @Builder.Default
    private List<String> permissionIds = new ArrayList<>();

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    private LocalDateTime updateTime;

    /**
     * 创建角色
     *
     * @param roleCode    角色代码
     * @param roleName    角色名称
     * @param description 角色描述
     * @return 角色领域模型
     */
    public static RoleModel create(String roleCode, String roleName, String description) {
        validateRoleCode(roleCode);
        LocalDateTime now = LocalDateTime.now();
        return RoleModel.builder()
                .id(UUID.randomUUID().toString())
                .roleCode(roleCode)
                .roleName(roleName)
                .description(description)
                .permissionIds(new ArrayList<>())
                .createTime(now)
                .updateTime(now)
                .build();
    }

    /**
     * 分配权限
     *
     * @param newPermissionIds 新的权限ID列表
     * @return 新的角色模型
     */
    public RoleModel assignPermissions(List<String> newPermissionIds) {
        List<String> updatedPermissionIds = new ArrayList<>(this.permissionIds);
        for (String permissionId : newPermissionIds) {
            if (!updatedPermissionIds.contains(permissionId)) {
                updatedPermissionIds.add(permissionId);
            }
        }
        return this.toBuilder()
                .permissionIds(updatedPermissionIds)
                .updateTime(LocalDateTime.now())
                .build();
    }

    /**
     * 移除权限
     *
     * @param permissionIdsToRemove 要移除的权限ID列表
     * @return 新的角色模型
     */
    public RoleModel removePermissions(List<String> permissionIdsToRemove) {
        List<String> updatedPermissionIds = new ArrayList<>(this.permissionIds);
        updatedPermissionIds.removeAll(permissionIdsToRemove);
        return this.toBuilder()
                .permissionIds(updatedPermissionIds)
                .updateTime(LocalDateTime.now())
                .build();
    }

    /**
     * 检查是否包含指定权限
     *
     * @param permissionId 权限ID
     * @return 是否包含
     */
    public boolean hasPermission(String permissionId) {
        return this.permissionIds.contains(permissionId);
    }

    /**
     * 更新角色信息
     *
     * @param roleName    角色名称
     * @param description 角色描述
     * @return 新的角色模型
     */
    public RoleModel updateInfo(String roleName, String description) {
        return this.toBuilder()
                .roleName(roleName != null ? roleName : this.roleName)
                .description(description != null ? description : this.description)
                .updateTime(LocalDateTime.now())
                .build();
    }

    /**
     * 验证角色代码格式
     *
     * @param roleCode 角色代码
     */
    private static void validateRoleCode(String roleCode) {
        if (roleCode == null || roleCode.trim().isEmpty()) {
            throw new IllegalArgumentException("角色代码不能为空");
        }
        if (!roleCode.matches("^[a-z0-9_]+$")) {
            throw new IllegalArgumentException("角色代码只能包含小写字母、数字和下划线");
        }
    }

}

